#Load packages
library(data.table)
Registered S3 method overwritten by 'data.table':
method from
print.data.table
data.table 1.14.8 using 1 threads (see ?getDTthreads). Latest news: r-datatable.com
**********
This installation of data.table has not detected OpenMP support. It should still work but in single-threaded mode.
This is a Mac. Please read https://mac.r-project.org/openmp/. Please engage with Apple and ask them for support. Check r-datatable.com for updates, and our Mac instructions here: https://github.com/Rdatatable/data.table/wiki/Installation. After several years of many reports of installation problems on Mac, it's time to gingerly point out that there have been no similar problems on Windows or Linux.
**********
library(tidyr)
library(haven)
library(ggplot2)
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:data.table’:
between, first, last
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(gridExtra)
Attaching package: ‘gridExtra’
The following object is masked from ‘package:dplyr’:
combine
library(lmtest)
Loading required package: zoo
Attaching package: ‘zoo’
The following objects are masked from ‘package:base’:
as.Date, as.Date.numeric
library(maps)
library(mapdata)
#Add data GPS
gps_data <- haven::read_dta("/Users/laurabazzigher/Documents/GitHub/risk_wvs/data/dataset/GPS_dataset_individual_level/individual_new.dta")
head(country_data)
Number of courtries
# Determine the number of different countries
number_of_countries <- length(unique(gps_data$country))
# Display the number of different countries
number_of_countries
[1] 76
Clean the data from missing values
# Clean the data by removing records with missing values
cleaned_data <- gps_data %>%
drop_na(country, isocode, risktaking, gender, age)
# Calculate the number of records removed per variable
records_removed_per_variable <- colSums(is.na(gps_data)) - colSums(is.na(cleaned_data))
# Display the cleaned data
cleaned_data
# Display the number of records removed per variable
records_removed_per_variable
country isocode ison region language date
0 0 0 0 0 0
id_gallup wgt patience risktaking posrecip negrecip
0 0 190 634 32 247
altruism trust subj_math_skills gender age
74 163 132 0 276
List of all variable
# List all variables
variable_list <- names(cleaned_data)
# Display the list of variables
print(variable_list)
[1] "country" "isocode" "ison" "region" "language"
[6] "date" "id_gallup" "wgt" "patience" "risktaking"
[11] "posrecip" "negrecip" "altruism" "trust" "subj_math_skills"
[16] "gender" "age"
#select only the variables of interest
cleaned_data <- cleaned_data %>%
select(country, isocode, ison, risktaking, gender, age)
cleaned_data
Calculate Z-Score for Age per Country
Create a new column “age_group” with the age categories
cleaned_data$agecat <- cut(
cleaned_data$age,
breaks = c(15, 20, 30, 40, 50, 60, 70, 80, Inf), # The category boundaries
labels = c("15-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80+"), # The category labels
right = FALSE # Left end (inclusive), right end (exclusive)
)
# Display the new column
head(cleaned_data)
########## ########## ########## Add
Hardship-list
########## ########## ########## ########## Get the
hardship facts together!!!!
# Lade GDP-Daten aus der CSV-Datei
gdp_data <- read.csv("/Users/laurabazzigher/Documents/GitHub/risk_wvs/data/dataset/GPS_dataset_individual_level/GDP_per_capita.csv")
# Merge der Daten basierend auf der gemeinsamen Variable "country" und "name"
cleaned_data <- merge(cleaned_data, gdp_data, by.x = "country", by.y = "name", all.x = TRUE)
# Anzeige der gemergten Daten
head(cleaned_data)
#select only the variables of interest
cleaned_data <- cleaned_data %>%
select(country, isocode, ison, risktaking, gender, age, z_score_age, agecat, value, date_of_information, ranking, region)
cleaned_data
Descriptive
Number of courtries after data cleaning
# Determine the number of different countries
number_of_countries <- length(unique(cleaned_data$country))
# Display the number of different countries
number_of_countries
[1] 76
#CODE FOR THE PRESENTATION ########### ########## ##########
Worldmap of the recorded countries
world_map <- map_data("world") # Create a world map with country borders
recorded_countries <- unique(cleaned_data$country) # Get the list of recorded countries from your cleaned_data
world_map$recorded <- ifelse(world_map$region %in% recorded_countries, "Recorded", "Not Recorded") # Create a new variable indicating whether a country has been recorded or not
# Plot the world map with recorded countries highlighted
ggplot(world_map, aes(x = long, y = lat, group = group, fill = recorded)) +
geom_polygon(color = "white") +
scale_fill_manual(values = c("Recorded" = "darkblue", "Not Recorded" = "lightgrey"), guide = "none") + # Set guide to "none" to remove the legend
theme_void() +
labs(title = "GPS", fill = "Status") +
theme(legend.position = "none", plot.title = element_text(hjust = 0.5)) # Remove legend and center the title

–> Add mean gender
–> add new columns to the datasetv –> put it to the data
preparation
Summarize data across all regions
summary_by_region <- cleaned_data %>%
group_by(region) %>%
summarize(
mean_age = mean(age, na.rm = TRUE),
mean_risk = mean(risktaking, na.rm = TRUE),
total_participants = n()
)
# Display the summarized data
print(summary_by_region)
All about the age
# Age Range
age_min <- min(cleaned_data$age, na.rm = TRUE)
age_max <- max(cleaned_data$age, na.rm = TRUE)
# Average Age
average_age <- mean(cleaned_data$age, na.rm = TRUE)
# Median Age
median_age <- median(cleaned_data$age, na.rm = TRUE)
# Display the age statistics
cat("Age Range: ", age_min, " to ", age_max, "\n")
Age Range: 15 to 99
cat("Average Age: ", average_age, "\n")
Average Age: 41.73605
cat("Median Age: ", median_age, "\n")
Median Age: 40
Number of participants in each age category
# number of participants in each age category
agecat_counts <- table(cleaned_data$agecat)
# Display the number of participants in the age categories
print(agecat_counts)
15-19 20-29 30-39 40-49 50-59 60-69 70-79 80+
6888 16872 15905 13583 11374 8570 4688 1559
Boxplot of Age Distribution per Country
ggplot(cleaned_data, aes(x = age)) +
geom_histogram(binwidth = 0.5, fill = "lightblue", color = "blue") +
labs(x = "Age", y = "Frequency", title = "Histogram of Age Distributionn") +
theme_minimal()

ggplot(cleaned_data, aes(x = country, y = age)) +
geom_boxplot(fill = "lightblue", color = "blue") +
labs(title = "Distribution of Age per Country", x = "Country", y = "Age") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

ggplot(cleaned_data, aes(x = country, y = risktaking)) +
geom_boxplot(fill = "lightblue", color = "blue") +
labs(title = "Distribution of Age per Country", x = "Country", y = "Risktaking") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

All about the gender
# Calculate the counts of females (gender = 1) and males (gender = 2)
gender_counts <- table(cleaned_data$gender)
# Display the counts
cat("Number of Females: ", gender_counts[1], "\n")
Number of Females: 36024
cat("Number of Males: ", gender_counts[2], "\n")
Number of Males: 43415
Table with country and gender
# Create a table that breaks down the number of participants by country and gender
gender_by_country <- xtabs(~ country + gender, data = cleaned_data)
# Rename columns and rows for better readability
colnames(gender_by_country) <- c("Female", "Male")
rownames(gender_by_country) <- unique(cleaned_data$country)
# Calculate the total participants by summing the rows
total_participants <- rowSums(gender_by_country)
# Create a data frame with country, total participants, female, and male
result_table <- data.frame(
country = rownames(gender_by_country),
total_participants = total_participants,
female = gender_by_country[, "Female"],
male = gender_by_country[, "Male"]
)
# Display the result table
result_table
Analysis of item risktaking
# Summary statistics for risktaking
risk_summary <- summary(cleaned_data$risktaking)
# Histogram of risktaking
ggplot(cleaned_data, aes(x = risktaking)) +
geom_histogram(binwidth = 1, fill = "lightblue", color = "blue", alpha = 0.7) +
labs(title = "Distribution of Risk-Taking", x = "Risk-Taking Score", y = "Frequency") +
theme_minimal()

# Boxplot of risktaking by gender
ggplot(cleaned_data, aes(x = as.factor(gender), y = risktaking, fill = as.factor(gender))) +
geom_boxplot() +
labs(title = "Risk-Taking by Gender", x = "Gender", y = "Risk-Taking Score") +
scale_x_discrete(labels = c("0" = "male", "1" = "female")) +
theme_minimal() +
guides(fill = FALSE)
Warning: The `<scale>` argument of `guides()` cannot be `FALSE`. Use "none" instead as of ggplot2 3.3.4.

# Risk vs age
ggplot(cleaned_data, aes(risktaking, age)) +
geom_point(size = 0.2) +
geom_smooth(method = "lm")

# Boxplot of risktaking by age group
cleaned_data$age_group <- cut(cleaned_data$age, breaks = c(0, 25, 35, 45, 55, Inf),
labels = c("18-25", "26-35", "36-45", "46-55", "56+"))
ggplot(cleaned_data, aes(x = age_group, y = risktaking, fill = age_group)) +
geom_boxplot() +
labs(title = "Risk-Taking by Age Group", x = "Age Group", y = "Risk-Taking Score") +
theme_minimal() +
guides(fill = FALSE)

# Boxplot of risktaking by country
ggplot(cleaned_data, aes(x = country, y = risktaking)) +
geom_boxplot(fill = "lightblue", color = "blue") +
labs(title = "Risk-Taking by Country", x = "Country", y = "Risk-Taking Score") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

Change backround change x-Achse acording to the info from the
presentation
Risk vs age with color-coded gender per Country
ggplot(cleaned_data, aes(z_score_age, risktaking, color = factor(gender))) +
geom_point(size = 0.1) +
geom_smooth(method = "lm") +
scale_color_manual(values = c("blue", "red"), labels = c("Male", "Female")) +
labs(color = "Gender")

Laura has to rewrite the code –> Table already included with the
lm
# Fit das Modell mit "age"
model_gender <- lm(risktaking ~ age + gender, data = cleaned_data)
# Intercept and Slope for age
intercept_age <- coef(model)["(Intercept)"]
slope_age <- coef(model)["age"]
summary(model)
Call:
lm(formula = risktaking ~ age * gender, data = cleaned_data)
Residuals:
Min 1Q Median 3Q Max
-2.3288 -0.6770 -0.0426 0.6446 3.0662
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.6413392 0.0131258 48.861 < 2e-16 ***
age -0.0124875 0.0002925 -42.692 < 2e-16 ***
gender -0.1285097 0.0178148 -7.214 5.50e-13 ***
age:gender -0.0021551 0.0003944 -5.464 4.66e-08 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.9644 on 79435 degrees of freedom
Multiple R-squared: 0.07001, Adjusted R-squared: 0.06998
F-statistic: 1993 on 3 and 79435 DF, p-value: < 2.2e-16
Laura has to rewrite the code –> Table already included with the
lm
analyze the results by using “Balkendiagramm”
what does 0 mean? // centered age = mean age of the sample
ggplot(data = regression_results, aes(x = country, y = intercept)) +
geom_bar(stat = "identity", fill = "blue") +
labs(title = "Intercepts for Risktaking by Country", x = "Country", y = "Intercept Value") +
theme(axis.text.x = element_text(angle = 90, hjust = 1))
View the countries with intercept values over 0.75
high_intercept_countries <- subset(regression_results, intercept > 0.75)
# View the countries with intercept values over 0.75
print(high_intercept_countries)
Scatterplots for ‘high_intercept_countries’ contains the top 17
countries
# Create scatterplots with regression lines for countries with intercept > 0.75
plots <- lapply(high_intercept_countries$country, function(country) {
p <- ggplot(subset(cleaned_data, country == country), aes(x = age, y = risktaking, color = factor(gender))) +
geom_point(size = 0.5) +
geom_smooth(method = "lm", formula = y ~ x, se = FALSE) +
labs(title = paste("Linear Regression for", country),
subtitle = paste("Intercept:", round(high_intercept_countries$intercept[high_intercept_countries$country == country], 2)),
color = "Gender") +
scale_color_manual(values = c("0" = "blue", "1" = "red"), labels = c("Male", "Female"))
print(p)
})
# Save the plots in a directory
dir.create("individual_country_plots", showWarnings = FALSE)
setwd("individual_country_plots")
for (i in seq_along(plots)) {
filename <- paste0("plot_", i, ".png")
ggsave(filename, plot = plots[[i]], width = 8, height = 6)
}
# Switch back to the original working directory
setwd("..")
print("Individual plots for countries with intercept > 0.75 are saved in the 'individual_country_plots' directory.")
Scatterplots for ‘high_intercept_countries’ contains the top 17
countries
plots <- lapply(high_intercept_countries$country, function(country) {
p <- ggplot(subset(cleaned_data, country == country), aes(x = ranking.x, y = risktaking, color = factor(gender))) +
geom_point(size = 0.5) +
geom_smooth(method = "lm", formula = y ~ x, se = FALSE) +
labs(title = paste("Linear Regression for", country),
subtitle = paste("Intercept:", round(high_intercept_countries$intercept[high_intercept_countries$country == country], 2)),
color = "Gender") +
scale_color_manual(values = c("0" = "blue", "1" = "red"), labels = c("Male", "Female"))
print(p)
})
# Save the plots in a directory
dir.create("individual_country_plots", showWarnings = FALSE)
setwd("individual_country_plots")
for (i in seq_along(plots)) {
filename <- paste0("plot_", i, ".png")
ggsave(filename, plot = plots[[i]], width = 8, height = 6)
}
# Switch back to the original working directory
setwd("..")
print("Individual plots for countries with intercept > 0.75 are saved in the 'individual_country_plots' directory.")
Create scatterplots with regression lines for individual
countries
# Examples for countries
regression_results <- data.frame(
country = c("Algeria", "Argentina", "Austria"),
intercept = c(0.92053422, 0.51698822, 0.42606684),
slope = c(-0.0146641801, -0.0115569623, -0.0108763042),
r_squared = c(5.232529e-02, 5.638271e-02, 3.539810e-02 )
)
# Create scatterplots with regression lines for each country
plots <- lapply(seq_len(nrow(regression_results)), function(i) {
country <- regression_results$country[i]
intercept <- regression_results$intercept[i]
slope <- regression_results$slope[i]
r_squared <- regression_results$r_squared[i]
p <- ggplot(subset(cleaned_data, country == country), aes(x = age, y = risktaking)) +
geom_point() +
geom_smooth(method = "lm", formula = y ~ x, se = FALSE, color = "blue") +
labs(title = paste("Linear Regression for", country),
subtitle = paste("Intercept:", round(intercept, 2),
"Slope:", round(slope, 2),
"R-squared:", round(r_squared, 2)))
print(p)
})
# Save the plots in a directory
dir.create("individual_country_plots", showWarnings = FALSE)
setwd("individual_country_plots")
for (i in seq_along(plots)) {
filename <- paste0("plot_", i, ".png")
ggsave(filename, plot = plots[[i]], width = 8, height = 6)
}
# Switch back to the original working directory
setwd("..")
print("Individual plots are saved in the 'individual_country_plots' directory.")
Scatterplot with include both individual country regression lines
and an overall regression line
# Calculate the overall regression line
overall_lm <- lm(risktaking ~ age, data = cleaned_data)
# Create a scatterplot with separate regression lines for each country
# and an overall regression line
ggplot(cleaned_data, aes(x = age, y = risktaking, color = country)) +
geom_point(size = 0.5) + # Adjust point size
geom_smooth(method = "lm", se = FALSE, size = 0.5) + # Solid line for individual countries
geom_abline(intercept = coef(overall_lm)[1], slope = coef(overall_lm)[2],
color = "black", size = 1) + # Add the overall regression line in red
labs(title = "Scatterplot with Regression Lines for risktaking and age by Country",
x = "Age", y = "Risktaking") +
theme(legend.position = "bottom", # Move the legend below the graph
legend.key.size = unit(0.1, "in")) # Adjust the size of the legend key
Combined List of all 3 files
Prepare Wave 5
# Load the data
WV5_data <- readRDS("/Users/laurabazzigher/Documents/GitHub/risk_wvs/data/dataset/WV6_dataset_wave_5_6/F00007944-WV5_Data_R_v20180912.rds") # Data of Wave 5
#rename the variables
WV5_data <- WV5_data_df %>%
rename(sex = V235, age = V237, country = V2, wave = V1, risktaking = V86)
WV5_data
#select only the variables of interest
WV5_data <- WV5_data %>%
select(sex, age, country, wave, risktaking)
WV5_data
#decode the country names
countrynames = read.csv("/Users/laurabazzigher/Documents/GitHub/risk_wvs/data/dataset/WV6_dataset_wave_5_6/countrynames.txt", header=FALSE,as.is=TRUE)
colnames(countrynames) = c("code", "name")
WV5_data$country_lab = countrynames$name [match(WV5_data$country, countrynames$code)]
table(WV5_data$country_lab)
WV5_data
Prepare Wave 6
#Read Dataset (Wave 6)
WV6_data <- load("/Users/laurabazzigher/Documents/GitHub/risk_wvs/data/dataset/WV6_dataset_wave_5_6/WV6_Data_R_v20201117.rdata")
WV6_data <- WV6_Data_R_v20201117
print(WV6_data)
#rename variables in Wave 6
WV6_data <- WV6_data %>%
rename(wave = V1, sex = V240, age = V242,country = V2, risktaking = V76)
#select only the variables of interest
WV6_data <- WV6_data %>%
select(wave, sex, age, country, sex,risktaking)
WV6_data
#decode daraset (Wave 6)
countrynames = read.csv("/Users/laurabazzigher/Documents/GitHub/risk_wvs/data/dataset/WV6_dataset_wave_5_6/countrynames.txt", header=FALSE,as.is=TRUE)
colnames(countrynames) = c("code", "name")
WV6_data$country_lab = countrynames$name [match(WV6_data$country, countrynames$code)]
table(WV6_data$country_lab)
WV6_data
Prepare GPS dataset (cleaned_data)
# Rename "Country" in "country_lab"
print(colnames(cleaned_data))
#combine the 2 dataset (Wave 6 + Wave 5)
WV5_data
WV6_data
data = rbind(WV5_data, WV6_data)
data
#number of countries
length(unique(data$country_lab))
Merge the datasets based on common variables
# Find common countries between the two datasets
common_countries <- intersect(data$country_lab, cleaned_data$country)
# Display the common countries
print(common_countries)
Find countries in “data” but not in “cleaned_data”
countries_only_in_data <- setdiff(data$country_lab, cleaned_data$country)
# Find countries in "cleaned_data" but not in "data"
countries_only_in_cleaned_data <- setdiff(cleaned_data$country, data$country_lab)
# Display the results
cat("Countries only in 'data':", countries_only_in_data, "\n")
cat("Countries only in 'cleaned_data':", countries_only_in_cleaned_data, "\n")
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKI0xvYWQgcGFja2FnZXMKYGBge3J9CmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeSh0aWR5cikKbGlicmFyeShoYXZlbikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShsbXRlc3QpCmxpYnJhcnkobWFwcykKbGlicmFyeShtYXBkYXRhKQpgYGAKCiNBZGQgZGF0YSBHUFMKYGBge3J9Cmdwc19kYXRhIDwtIGhhdmVuOjpyZWFkX2R0YSgiL1VzZXJzL2xhdXJhYmF6emlnaGVyL0RvY3VtZW50cy9HaXRIdWIvcmlza193dnMvZGF0YS9kYXRhc2V0L0dQU19kYXRhc2V0X2luZGl2aWR1YWxfbGV2ZWwvaW5kaXZpZHVhbF9uZXcuZHRhIikKCmhlYWQoY291bnRyeV9kYXRhKQpgYGAKIyBOdW1iZXIgb2YgY291cnRyaWVzIApgYGB7cn0KIyBEZXRlcm1pbmUgdGhlIG51bWJlciBvZiBkaWZmZXJlbnQgY291bnRyaWVzCm51bWJlcl9vZl9jb3VudHJpZXMgPC0gbGVuZ3RoKHVuaXF1ZShncHNfZGF0YSRjb3VudHJ5KSkKCiMgRGlzcGxheSB0aGUgbnVtYmVyIG9mIGRpZmZlcmVudCBjb3VudHJpZXMKbnVtYmVyX29mX2NvdW50cmllcwpgYGAKCiMgQ2xlYW4gdGhlIGRhdGEgZnJvbSBtaXNzaW5nIHZhbHVlcwpgYGB7cn0KIyBDbGVhbiB0aGUgZGF0YSBieSByZW1vdmluZyByZWNvcmRzIHdpdGggbWlzc2luZyB2YWx1ZXMKY2xlYW5lZF9kYXRhIDwtIGdwc19kYXRhICU+JQogIGRyb3BfbmEoY291bnRyeSwgaXNvY29kZSwgcmlza3Rha2luZywgZ2VuZGVyLCBhZ2UpCgojIENhbGN1bGF0ZSB0aGUgbnVtYmVyIG9mIHJlY29yZHMgcmVtb3ZlZCBwZXIgdmFyaWFibGUKcmVjb3Jkc19yZW1vdmVkX3Blcl92YXJpYWJsZSA8LSBjb2xTdW1zKGlzLm5hKGdwc19kYXRhKSkgLSBjb2xTdW1zKGlzLm5hKGNsZWFuZWRfZGF0YSkpCgojIERpc3BsYXkgdGhlIGNsZWFuZWQgZGF0YQpjbGVhbmVkX2RhdGEKCiMgRGlzcGxheSB0aGUgbnVtYmVyIG9mIHJlY29yZHMgcmVtb3ZlZCBwZXIgdmFyaWFibGUKcmVjb3Jkc19yZW1vdmVkX3Blcl92YXJpYWJsZQpgYGAKCiMgTGlzdCBvZiBhbGwgdmFyaWFibGUKYGBge3J9CiMgTGlzdCBhbGwgdmFyaWFibGVzCnZhcmlhYmxlX2xpc3QgPC0gbmFtZXMoY2xlYW5lZF9kYXRhKSAKCiMgRGlzcGxheSB0aGUgbGlzdCBvZiB2YXJpYWJsZXMKcHJpbnQodmFyaWFibGVfbGlzdCkKYGBgCiNzZWxlY3Qgb25seSB0aGUgdmFyaWFibGVzIG9mIGludGVyZXN0CmBgYHtyfQpjbGVhbmVkX2RhdGEgPC0gY2xlYW5lZF9kYXRhICU+JQogIHNlbGVjdChjb3VudHJ5LCBpc29jb2RlLCBpc29uLCByaXNrdGFraW5nLCBnZW5kZXIsIGFnZSkKY2xlYW5lZF9kYXRhCmBgYAoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgQ2FsY3VsYXRlIFotU2NvcmUgZm9yIEFnZSBwZXIgQ291bnRyeQojIyMjIyMjIyMjIyMjIyBNZWRpYW4gPSA0MCAvLyBTRCA9IDE1IApgYGB7cn0KY2xlYW5lZF9kYXRhIDwtIGNsZWFuZWRfZGF0YSAlPiUKICBncm91cF9ieShjb3VudHJ5KSAlPiUKICBtdXRhdGUoel9zY29yZV9hZ2UgPSBzY2FsZShhZ2UpKQoKIyBEaXNwbGF5IHRoZSBuZXcgY29sdW1uIHdpdGggWi1TY29yZXMgcGVyIENvdW50cnkKaGVhZChjbGVhbmVkX2RhdGEpCmBgYAoKIyBDcmVhdGUgYSBuZXcgY29sdW1uICJhZ2VfZ3JvdXAiIHdpdGggdGhlIGFnZSBjYXRlZ29yaWVzCmBgYHtyfQpjbGVhbmVkX2RhdGEkYWdlY2F0IDwtIGN1dCgKICBjbGVhbmVkX2RhdGEkYWdlLAogIGJyZWFrcyA9IGMoMTUsIDIwLCAzMCwgNDAsIDUwLCA2MCwgNzAsIDgwLCBJbmYpLCAjIFRoZSBjYXRlZ29yeSBib3VuZGFyaWVzCiAgbGFiZWxzID0gYygiMTUtMTkiLCAiMjAtMjkiLCAiMzAtMzkiLCAiNDAtNDkiLCAiNTAtNTkiLCAiNjAtNjkiLCAiNzAtNzkiLCAiODArIiksICMgVGhlIGNhdGVnb3J5IGxhYmVscwogIHJpZ2h0ID0gRkFMU0UgIyBMZWZ0IGVuZCAoaW5jbHVzaXZlKSwgcmlnaHQgZW5kIChleGNsdXNpdmUpCikKCiMgRGlzcGxheSB0aGUgbmV3IGNvbHVtbgpoZWFkKGNsZWFuZWRfZGF0YSkKYGBgCgojIyMjIyMjIyMjICMjIyMjIyMjIyMgIyMjIyMjIyMjIyAjIyMjIyMjIyMjIEFkZCBIYXJkc2hpcC1saXN0CiMjIyMjIyMjIyMgIyMjIyMjIyMjIyAjIyMjIyMjIyMjICMjIyMjIyMjIyMgIyMjIyMjIyMjIyBHZXQgdGhlIGhhcmRzaGlwIGZhY3RzIHRvZ2V0aGVyISEhIQpgYGB7cn0KIyBMYWRlIEdEUC1EYXRlbiBhdXMgZGVyIENTVi1EYXRlaQpnZHBfZGF0YSA8LSByZWFkLmNzdigiL1VzZXJzL2xhdXJhYmF6emlnaGVyL0RvY3VtZW50cy9HaXRIdWIvcmlza193dnMvZGF0YS9kYXRhc2V0L0dQU19kYXRhc2V0X2luZGl2aWR1YWxfbGV2ZWwvR0RQX3Blcl9jYXBpdGEuY3N2IikKCiMgTWVyZ2UgZGVyIERhdGVuIGJhc2llcmVuZCBhdWYgZGVyIGdlbWVpbnNhbWVuIFZhcmlhYmxlICJjb3VudHJ5IiB1bmQgIm5hbWUiCmNsZWFuZWRfZGF0YSA8LSBtZXJnZShjbGVhbmVkX2RhdGEsIGdkcF9kYXRhLCBieS54ID0gImNvdW50cnkiLCBieS55ID0gIm5hbWUiLCBhbGwueCA9IFRSVUUpCgojIEFuemVpZ2UgZGVyIGdlbWVyZ3RlbiBEYXRlbgpoZWFkKGNsZWFuZWRfZGF0YSkKYGBgCiNzZWxlY3Qgb25seSB0aGUgdmFyaWFibGVzIG9mIGludGVyZXN0CmBgYHtyfQpjbGVhbmVkX2RhdGEgPC0gY2xlYW5lZF9kYXRhICU+JQogIHNlbGVjdChjb3VudHJ5LCBpc29jb2RlLCBpc29uLCByaXNrdGFraW5nLCBnZW5kZXIsIGFnZSwgel9zY29yZV9hZ2UsIGFnZWNhdCwgdmFsdWUsIGRhdGVfb2ZfaW5mb3JtYXRpb24sIHJhbmtpbmcsIHJlZ2lvbikKY2xlYW5lZF9kYXRhCmBgYAoKIyBFeHRyYWhpZXJlIGRpZSBTcGFsdGUgInJhbmtpbmciIGF1cyBkZW0gZ2VtZXJndGVuIERhdGVucmFobWVuCmBgYHtyfQojIEFuemFobCBkZXIgVGVpbG5laG1lbmRlbiBwcm8gUmFua2luZyB1bmQgTGFuZApwYXJ0aWNpcGFudHNfYnlfcmFua2luZyA8LSBjbGVhbmVkX2RhdGEgJT4lCiAgZ3JvdXBfYnkocmFua2luZywgY291bnRyeSkgJT4lCiAgc3VtbWFyaXplKHBhcnRpY2lwYW50X2NvdW50ID0gbigpKQoKIyBBbnplaWdlIGRlciBMaXN0ZQpwcmludChwYXJ0aWNpcGFudHNfYnlfcmFua2luZykKCndyaXRlLnhsc3gocGFydGljaXBhbnRzX2J5X2NvdW50cnksICJUZWlsbmVobWVyX25hY2hfTGFuZC54bHN4Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgojIFBmYWQsIHdvIGRpZSBFeGNlbC1EYXRlaSBnZXNwZWljaGVydCB3ZXJkZW4gc29sbApleGNlbF9wYXRoIDwtICIvVXNlcnMvbGF1cmFiYXp6aWdoZXIvRG9jdW1lbnRzL0dpdEh1Yi9yaXNrX3d2cy9kYXRhL2RhdGFzZXQvIgoKIyBFeGNlbC1EYXRlaSBlcnN0ZWxsZW4Kd3JpdGUueGxzeChwYXJ0aWNpcGFudHNfYnlfY291bnRyeSwgZXhjZWxfcGF0aCwgcm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBEZXNjcmlwdGl2ZSAKCiMgTnVtYmVyIG9mIGNvdXJ0cmllcyBhZnRlciBkYXRhIGNsZWFuaW5nCmBgYHtyfQojIERldGVybWluZSB0aGUgbnVtYmVyIG9mIGRpZmZlcmVudCBjb3VudHJpZXMKbnVtYmVyX29mX2NvdW50cmllcyA8LSBsZW5ndGgodW5pcXVlKGNsZWFuZWRfZGF0YSRjb3VudHJ5KSkKCiMgRGlzcGxheSB0aGUgbnVtYmVyIG9mIGRpZmZlcmVudCBjb3VudHJpZXMKbnVtYmVyX29mX2NvdW50cmllcwpgYGAKCiMjIyMjIyMjIyMjCiMjIyMjIyMjIyMKIyMjIyMjIyMjIwojQ09ERSBGT1IgVEhFIFBSRVNFTlRBVElPTiAKIyMjIyMjIyMjIyMKIyMjIyMjIyMjIwojIyMjIyMjIyMjCgojIFdvcmxkbWFwIG9mIHRoZSByZWNvcmRlZCBjb3VudHJpZXMKYGBge3J9CndvcmxkX21hcCA8LSBtYXBfZGF0YSgid29ybGQiKSAjIENyZWF0ZSBhIHdvcmxkIG1hcCB3aXRoIGNvdW50cnkgYm9yZGVycwoKcmVjb3JkZWRfY291bnRyaWVzIDwtIHVuaXF1ZShjbGVhbmVkX2RhdGEkY291bnRyeSkgIyBHZXQgdGhlIGxpc3Qgb2YgcmVjb3JkZWQgY291bnRyaWVzIGZyb20geW91ciBjbGVhbmVkX2RhdGEKCndvcmxkX21hcCRyZWNvcmRlZCA8LSBpZmVsc2Uod29ybGRfbWFwJHJlZ2lvbiAlaW4lIHJlY29yZGVkX2NvdW50cmllcywgIlJlY29yZGVkIiwgIk5vdCBSZWNvcmRlZCIpICMgQ3JlYXRlIGEgbmV3IHZhcmlhYmxlIGluZGljYXRpbmcgd2hldGhlciBhIGNvdW50cnkgaGFzIGJlZW4gcmVjb3JkZWQgb3Igbm90CgojIFBsb3QgdGhlIHdvcmxkIG1hcCB3aXRoIHJlY29yZGVkIGNvdW50cmllcyBoaWdobGlnaHRlZApnZ3Bsb3Qod29ybGRfbWFwLCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSByZWNvcmRlZCkpICsKICBnZW9tX3BvbHlnb24oY29sb3IgPSAid2hpdGUiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiUmVjb3JkZWQiID0gImRhcmtibHVlIiwgIk5vdCBSZWNvcmRlZCIgPSAibGlnaHRncmV5IiksIGd1aWRlID0gIm5vbmUiKSArICAjIFNldCBndWlkZSB0byAibm9uZSIgdG8gcmVtb3ZlIHRoZSBsZWdlbmQKICB0aGVtZV92b2lkKCkgKwogIGxhYnModGl0bGUgPSAiR1BTIiwgZmlsbCA9ICJTdGF0dXMiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgICMgUmVtb3ZlIGxlZ2VuZCBhbmQgY2VudGVyIHRoZSB0aXRsZQoKYGBgCiMjIyMjIyMjIyMjCiMjIyMjIyMjIyMgLS0+IEFkZCBtZWFuIGdlbmRlciAKLS0+IGFkZCBuZXcgY29sdW1ucyB0byB0aGUgZGF0YXNldHYgCi0tPiBwdXQgaXQgdG8gdGhlIGRhdGEgcHJlcGFyYXRpb24gCgojIFN1bW1hcml6ZSBkYXRhIGFjcm9zcyBhbGwgcmVnaW9ucwpgYGB7cn0Kc3VtbWFyeV9ieV9yZWdpb24gPC0gY2xlYW5lZF9kYXRhICU+JQogIGdyb3VwX2J5KHJlZ2lvbikgJT4lCiAgc3VtbWFyaXplKAogICAgbWVhbl9hZ2UgPSBtZWFuKGFnZSwgbmEucm0gPSBUUlVFKSwKICAgIG1lYW5fcmlzayA9IG1lYW4ocmlza3Rha2luZywgbmEucm0gPSBUUlVFKSwKICAgIHRvdGFsX3BhcnRpY2lwYW50cyA9IG4oKQogICkKCiMgRGlzcGxheSB0aGUgc3VtbWFyaXplZCBkYXRhCnByaW50KHN1bW1hcnlfYnlfcmVnaW9uKQpgYGAKCiMgQWxsIGFib3V0IHRoZSBhZ2UKYGBge3J9CiMgQWdlIFJhbmdlCmFnZV9taW4gPC0gbWluKGNsZWFuZWRfZGF0YSRhZ2UsIG5hLnJtID0gVFJVRSkKYWdlX21heCA8LSBtYXgoY2xlYW5lZF9kYXRhJGFnZSwgbmEucm0gPSBUUlVFKQoKIyBBdmVyYWdlIEFnZQphdmVyYWdlX2FnZSA8LSBtZWFuKGNsZWFuZWRfZGF0YSRhZ2UsIG5hLnJtID0gVFJVRSkKCiMgTWVkaWFuIEFnZQptZWRpYW5fYWdlIDwtIG1lZGlhbihjbGVhbmVkX2RhdGEkYWdlLCBuYS5ybSA9IFRSVUUpCgojIERpc3BsYXkgdGhlIGFnZSBzdGF0aXN0aWNzCmNhdCgiQWdlIFJhbmdlOiAiLCBhZ2VfbWluLCAiIHRvICIsIGFnZV9tYXgsICJcbiIpCmNhdCgiQXZlcmFnZSBBZ2U6ICIsIGF2ZXJhZ2VfYWdlLCAiXG4iKQpjYXQoIk1lZGlhbiBBZ2U6ICIsIG1lZGlhbl9hZ2UsICJcbiIpCmBgYAoKIyBOdW1iZXIgb2YgcGFydGljaXBhbnRzIGluIGVhY2ggYWdlIGNhdGVnb3J5CmBgYHtyfQojIG51bWJlciBvZiBwYXJ0aWNpcGFudHMgaW4gZWFjaCBhZ2UgY2F0ZWdvcnkKYWdlY2F0X2NvdW50cyA8LSB0YWJsZShjbGVhbmVkX2RhdGEkYWdlY2F0KQoKIyBEaXNwbGF5IHRoZSBudW1iZXIgb2YgcGFydGljaXBhbnRzIGluIHRoZSBhZ2UgY2F0ZWdvcmllcwpwcmludChhZ2VjYXRfY291bnRzKQpgYGAKCiMgQm94cGxvdCBvZiBBZ2UgRGlzdHJpYnV0aW9uIHBlciBDb3VudHJ5IApgYGB7cn0KZ2dwbG90KGNsZWFuZWRfZGF0YSwgYWVzKHggPSBhZ2UpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAwLjUsIGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3IgPSAiYmx1ZSIpICsKICBsYWJzKHggPSAiQWdlIiwgeSA9ICJGcmVxdWVuY3kiLCB0aXRsZSA9ICJIaXN0b2dyYW0gb2YgQWdlIERpc3RyaWJ1dGlvbm4iKSArCiAgdGhlbWVfbWluaW1hbCgpCgpnZ3Bsb3QoY2xlYW5lZF9kYXRhLCBhZXMoeCA9IGNvdW50cnksIHkgPSBhZ2UpKSArCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3IgPSAiYmx1ZSIpICsKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBBZ2UgcGVyIENvdW50cnkiLCB4ID0gIkNvdW50cnkiLCB5ID0gIkFnZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdD0xKSkKCmdncGxvdChjbGVhbmVkX2RhdGEsIGFlcyh4ID0gY291bnRyeSwgeSA9IHJpc2t0YWtpbmcpKSArCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3IgPSAiYmx1ZSIpICsKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBBZ2UgcGVyIENvdW50cnkiLCB4ID0gIkNvdW50cnkiLCB5ID0gIlJpc2t0YWtpbmciKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpCmBgYAoKCiMgQWxsIGFib3V0IHRoZSBnZW5kZXIKYGBge3J9CiMgQ2FsY3VsYXRlIHRoZSBjb3VudHMgb2YgZmVtYWxlcyAoZ2VuZGVyID0gMSkgYW5kIG1hbGVzIChnZW5kZXIgPSAyKQpnZW5kZXJfY291bnRzIDwtIHRhYmxlKGNsZWFuZWRfZGF0YSRnZW5kZXIpCgojIERpc3BsYXkgdGhlIGNvdW50cwpjYXQoIk51bWJlciBvZiBGZW1hbGVzOiAiLCBnZW5kZXJfY291bnRzWzFdLCAiXG4iKQpjYXQoIk51bWJlciBvZiBNYWxlczogIiwgZ2VuZGVyX2NvdW50c1syXSwgIlxuIikKYGBgCgojIFRhYmxlIHdpdGggY291bnRyeSBhbmQgZ2VuZGVyCmBgYHtyfQojIENyZWF0ZSBhIHRhYmxlIHRoYXQgYnJlYWtzIGRvd24gdGhlIG51bWJlciBvZiBwYXJ0aWNpcGFudHMgYnkgY291bnRyeSBhbmQgZ2VuZGVyCmdlbmRlcl9ieV9jb3VudHJ5IDwtIHh0YWJzKH4gY291bnRyeSArIGdlbmRlciwgZGF0YSA9IGNsZWFuZWRfZGF0YSkKCiMgUmVuYW1lIGNvbHVtbnMgYW5kIHJvd3MgZm9yIGJldHRlciByZWFkYWJpbGl0eQpjb2xuYW1lcyhnZW5kZXJfYnlfY291bnRyeSkgPC0gYygiRmVtYWxlIiwgIk1hbGUiKQpyb3duYW1lcyhnZW5kZXJfYnlfY291bnRyeSkgPC0gdW5pcXVlKGNsZWFuZWRfZGF0YSRjb3VudHJ5KQoKIyBDYWxjdWxhdGUgdGhlIHRvdGFsIHBhcnRpY2lwYW50cyBieSBzdW1taW5nIHRoZSByb3dzCnRvdGFsX3BhcnRpY2lwYW50cyA8LSByb3dTdW1zKGdlbmRlcl9ieV9jb3VudHJ5KQoKIyBDcmVhdGUgYSBkYXRhIGZyYW1lIHdpdGggY291bnRyeSwgdG90YWwgcGFydGljaXBhbnRzLCBmZW1hbGUsIGFuZCBtYWxlCnJlc3VsdF90YWJsZSA8LSBkYXRhLmZyYW1lKAogIGNvdW50cnkgPSByb3duYW1lcyhnZW5kZXJfYnlfY291bnRyeSksCiAgdG90YWxfcGFydGljaXBhbnRzID0gdG90YWxfcGFydGljaXBhbnRzLAogIGZlbWFsZSA9IGdlbmRlcl9ieV9jb3VudHJ5WywgIkZlbWFsZSJdLAogIG1hbGUgPSBnZW5kZXJfYnlfY291bnRyeVssICJNYWxlIl0KKQoKIyBEaXNwbGF5IHRoZSByZXN1bHQgdGFibGUKcmVzdWx0X3RhYmxlCmBgYAojIEFuYWx5c2lzIG9mIGl0ZW0gcmlza3Rha2luZyAKYGBge3J9CiMgU3VtbWFyeSBzdGF0aXN0aWNzIGZvciByaXNrdGFraW5nCnJpc2tfc3VtbWFyeSA8LSBzdW1tYXJ5KGNsZWFuZWRfZGF0YSRyaXNrdGFraW5nKQoKIyBIaXN0b2dyYW0gb2Ygcmlza3Rha2luZwpnZ3Bsb3QoY2xlYW5lZF9kYXRhLCBhZXMoeCA9IHJpc2t0YWtpbmcpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IDAuNykgKwogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFJpc2stVGFraW5nIiwgeCA9ICJSaXNrLVRha2luZyBTY29yZSIsIHkgPSAiRnJlcXVlbmN5IikgKwogIHRoZW1lX21pbmltYWwoKQoKIyBCb3hwbG90IG9mIHJpc2t0YWtpbmcgYnkgZ2VuZGVyCmdncGxvdChjbGVhbmVkX2RhdGEsIGFlcyh4ID0gYXMuZmFjdG9yKGdlbmRlciksIHkgPSByaXNrdGFraW5nLCBmaWxsID0gYXMuZmFjdG9yKGdlbmRlcikpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIGxhYnModGl0bGUgPSAiUmlzay1UYWtpbmcgYnkgR2VuZGVyIiwgeCA9ICJHZW5kZXIiLCB5ID0gIlJpc2stVGFraW5nIFNjb3JlIikgKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygiMCIgPSAibWFsZSIsICIxIiA9ICJmZW1hbGUiKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkKCiMgUmlzayB2cyBhZ2UKZ2dwbG90KGNsZWFuZWRfZGF0YSwgYWVzKHJpc2t0YWtpbmcsIGFnZSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjIpICsgIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpCgojIEJveHBsb3Qgb2Ygcmlza3Rha2luZyBieSBhZ2UgZ3JvdXAKY2xlYW5lZF9kYXRhJGFnZV9ncm91cCA8LSBjdXQoY2xlYW5lZF9kYXRhJGFnZSwgYnJlYWtzID0gYygwLCAyNSwgMzUsIDQ1LCA1NSwgSW5mKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIjE4LTI1IiwgIjI2LTM1IiwgIjM2LTQ1IiwgIjQ2LTU1IiwgIjU2KyIpKQpnZ3Bsb3QoY2xlYW5lZF9kYXRhLCBhZXMoeCA9IGFnZV9ncm91cCwgeSA9IHJpc2t0YWtpbmcsIGZpbGwgPSBhZ2VfZ3JvdXApKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIGxhYnModGl0bGUgPSAiUmlzay1UYWtpbmcgYnkgQWdlIEdyb3VwIiwgeCA9ICJBZ2UgR3JvdXAiLCB5ID0gIlJpc2stVGFraW5nIFNjb3JlIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkKCiMgQm94cGxvdCBvZiByaXNrdGFraW5nIGJ5IGNvdW50cnkKZ2dwbG90KGNsZWFuZWRfZGF0YSwgYWVzKHggPSBjb3VudHJ5LCB5ID0gcmlza3Rha2luZykpICsKICBnZW9tX2JveHBsb3QoZmlsbCA9ICJsaWdodGJsdWUiLCBjb2xvciA9ICJibHVlIikgKwogIGxhYnModGl0bGUgPSAiUmlzay1UYWtpbmcgYnkgQ291bnRyeSIsIHggPSAiQ291bnRyeSIsIHkgPSAiUmlzay1UYWtpbmcgU2NvcmUiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpCmBgYAoKIyMjIyMjIyMjIyMKIyMjIyMjIyMjIyMKIyMjIyMjIyMjIyMKQ2hhbmdlIGJhY2tyb3VuZCAKY2hhbmdlIHgtQWNoc2UgYWNvcmRpbmcgdG8gdGhlIGluZm8gZnJvbSB0aGUgcHJlc2VudGF0aW9uCgojIFJpc2sgdnMgYWdlIHdpdGggY29sb3ItY29kZWQgZ2VuZGVyIHBlciBDb3VudHJ5CmBgYHtyfQpnZ3Bsb3QoY2xlYW5lZF9kYXRhLCBhZXMoel9zY29yZV9hZ2UsIHJpc2t0YWtpbmcsIGNvbG9yID0gZmFjdG9yKGdlbmRlcikpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArICAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImJsdWUiLCAicmVkIiksIGxhYmVscyA9IGMoIk1hbGUiLCAiRmVtYWxlIikpICsKICBsYWJzKGNvbG9yID0gIkdlbmRlciIpCmBgYAoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKCiMjIyMjIyMjIyMjCiMjIyMjIyMjIyMjCiMjIyMjIyMjIyMjCkxhdXJhIGhhcyB0byByZXdyaXRlIHRoZSBjb2RlIC0tPiBUYWJsZSBhbHJlYWR5IGluY2x1ZGVkIHdpdGggdGhlIGxtCgpgYGB7cn0KIyBGaXQgZGFzIE1vZGVsbCBtaXQgImFnZSIKbW9kZWxfZ2VuZGVyIDwtIGxtKHJpc2t0YWtpbmcgfiBhZ2UgKyBnZW5kZXIsIGRhdGEgPSBjbGVhbmVkX2RhdGEpCgojIEludGVyY2VwdCBhbmQgU2xvcGUgZm9yIGFnZQppbnRlcmNlcHRfYWdlIDwtIGNvZWYobW9kZWwpWyIoSW50ZXJjZXB0KSJdCnNsb3BlX2FnZSA8LSBjb2VmKG1vZGVsKVsiYWdlIl0KCnN1bW1hcnkobW9kZWwpCmBgYAoKIyMjIyMjIyMjIyMKIyMjIyMjIyMjIyMKIyMjIyMjIyMjIyMKTGF1cmEgaGFzIHRvIHJld3JpdGUgdGhlIGNvZGUgLS0+IFRhYmxlIGFscmVhZHkgaW5jbHVkZWQgd2l0aCB0aGUgbG0KCgojIENyZWF0ZSBhIHRhYmxlIHdpdGggdGhlIGZvbGxvd2luZyBpbmZvcm1hdGlvbjogY291bnRyeSwgaXNvY29kZSwgbiAoY291bnQgb2YgcGFydGljaXBhbnRzKSwgZmVtYWxlIHBlcmNlbnRhZ2UgKCUpLCBtZWFuIGFnZSwgYWdlIHJhbmdlLCBhbmQgcmlza3Rha2luZwoKIyMjIEZvdXIgbG91cCAKR3JvdXAgYnkgY291bnRyeQptdXRhdGUgaW50ZXJjZXB0IApydW4gYW5kIHNhdmUgaW50ZXJjZXB0IG1vZGVsIApgYGB7cn0KIyBHcm91cCB0aGUgZGF0YSBieSBjb3VudHJ5CnRhYmxlX2RhdGEgPC0gZ3BzX2RhdGEgJT4lCiAgZ3JvdXBfYnkoY291bnRyeSwgaXNvY29kZSkgJT4lCiAgc3VtbWFyaXplKAogICAgbiA9IG4oKSwKICAgIGZlbWFsZV9wZXJjZW50YWdlID0gbWVhbihnZW5kZXIgPT0gMSkgKiAxMDAsCiAgICBtZWFuX2FnZSA9IG1lYW4oYWdlLCBuYS5ybSA9IFRSVUUpLAogICAgYWdlX3JhbmdlID0gcGFzdGUobWluKGFnZSwgbmEucm0gPSBUUlVFKSwgIi0iLCBtYXgoYWdlLCBuYS5ybSA9IFRSVUUpKSwKICAgIG1lYW5fcmlza3Rha2luZyA9IG1lYW4ocmlza3Rha2luZywgbmEucm0gPSBUUlVFKQogICkKCiMgSW50ZXJjZXB0IGFuZCBzbG9wZSBmb3IgYWdlCmludGVyY2VwdF9hZ2UgPC0gMC41NzU5NzAxCnNsb3BlX2FnZSA8LSAtMC4wMTM3OTAyCgojIEludGVyY2VwdCBhbmQgc2xvcGUgZm9yIGdlbmRlcgppbnRlcmNlcHRfZ2VuZGVyIDwtIDAuMTI0NjY2IApzbG9wZV9nZW5kZXIgPC0gLTAuMjI3MzM4IAoKIyBBZGQgdGhlIGludGVyY2VwdCBhbmQgc2xvcGUgaW5mb3JtYXRpb24gdG8gdGhlIHRhYmxlCnRhYmxlX2RhdGEgPC0gdGFibGVfZGF0YSAlPiUKICBtdXRhdGUoCiAgICBpbnRlcmNlcHRfYWdlID0gaW50ZXJjZXB0X2FnZSwKICAgIHNsb3BlX2FnZSA9IHNsb3BlX2FnZSwKICAgIGludGVyY2VwdF9nZW5kZXIgPSBpbnRlcmNlcHRfZ2VuZGVyLAogICAgc2xvcGVfZ2VuZGVyID0gc2xvcGVfZ2VuZGVyLAogICkKCiMgRGlzcGxheSB0aGUgdXBkYXRlZCB0YWJsZQp0YWJsZV9kYXRhCmBgYAoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCgoKI1ByZXBhcmluZyBmb3IgbGluZWFyIHJlZ3Jlc3Npb24KYGBge3J9CiMgQ2hlY2sgZm9yIG1pc3NpbmcgdmFsdWVzIGluICdDb3VudHJ5JyBhbmQgJ1Jpc2t0YWtpbmcnIGNvbHVtbnMKbWlzc2luZ19jb3VudHJ5IDwtIGFueU5BKGNsZWFuZWRfZGF0YSRjb3VudHJ5KQptaXNzaW5nX3Jpc2t0YWtpbmcgPC0gYW55TkEoY2xlYW5lZF9kYXRhJHJpc2t0YWtpbmcpCgojIFByaW50IHRoZSByZXN1bHRzCmNhdCgiTWlzc2luZyB2YWx1ZXMgaW4gJ0NvdW50cnknOiAiLCBtaXNzaW5nX2NvdW50cnksICJcbiIpCmNhdCgiTWlzc2luZyB2YWx1ZXMgaW4gJ1Jpc2t0YWtpbmcnOiAiLCBtaXNzaW5nX3Jpc2t0YWtpbmcsICJcbiIpCgpgYGAKCgpgYGB7cn0KIyBDbGVhbiB0aGUgZGF0YSBieSByZW1vdmluZyByZWNvcmRzIHdpdGggbWlzc2luZyB2YWx1ZXMKY2xlYW5lZF9kYXRhIDwtIGdwc19kYXRhICU+JQogIGRyb3BfbmEoY291bnRyeSwgcmlza3Rha2luZywgYWdlKQoKIyBTcGxpdCB0aGUgZGF0YSBieSBjb3VudHJ5IGFuZCBwZXJmb3JtIGxpbmVhciByZWdyZXNzaW9uIGZvciBlYWNoIGNvdW50cnkKcmVncmVzc2lvbl9yZXN1bHRzIDwtIGNsZWFuZWRfZGF0YSAlPiUKICBncm91cF9ieShjb3VudHJ5KSAlPiUKICBkbyhtb2RlbCA9IGxtKHJpc2t0YWtpbmcgfiBhZ2UsIGRhdGEgPSAuKSkgJT4lCiAgc3VtbWFyaXplKAogICAgY291bnRyeSA9IGZpcnN0KGNvdW50cnkpLAogICAgaW50ZXJjZXB0ID0gc3VtbWFyeShtb2RlbCkkY29lZmZpY2llbnRzWzFdLAogICAgc2xvcGUgPSBzdW1tYXJ5KG1vZGVsKSRjb2VmZmljaWVudHNbMl0sCiAgICByX3NxdWFyZWQgPSBzdW1tYXJ5KG1vZGVsKSRyLnNxdWFyZWQKICApCgojIERpc3BsYXkgcmVncmVzc2lvbiByZXN1bHRzIGZvciBlYWNoIGNvdW50cnkKcHJpbnQocmVncmVzc2lvbl9yZXN1bHRzKQpgYGAKCgojIGFuYWx5emUgdGhlIHJlc3VsdHMgYnkgdXNpbmcgIkJhbGtlbmRpYWdyYW1tIgojIyMjIyMgd2hhdCBkb2VzIDAgbWVhbj8gLy8gY2VudGVyZWQgYWdlID0gbWVhbiBhZ2Ugb2YgdGhlIHNhbXBsZQpgYGB7cn0KZ2dwbG90KGRhdGEgPSByZWdyZXNzaW9uX3Jlc3VsdHMsIGFlcyh4ID0gY291bnRyeSwgeSA9IGludGVyY2VwdCkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJibHVlIikgKwogIGxhYnModGl0bGUgPSAiSW50ZXJjZXB0cyBmb3IgUmlza3Rha2luZyBieSBDb3VudHJ5IiwgeCA9ICJDb3VudHJ5IiwgeSA9ICJJbnRlcmNlcHQgVmFsdWUiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSkKYGBgCiMgVmlldyB0aGUgY291bnRyaWVzIHdpdGggaW50ZXJjZXB0IHZhbHVlcyBvdmVyIDAuNzUKYGBge3J9CmhpZ2hfaW50ZXJjZXB0X2NvdW50cmllcyA8LSBzdWJzZXQocmVncmVzc2lvbl9yZXN1bHRzLCBpbnRlcmNlcHQgPiAwLjc1KQoKIyBWaWV3IHRoZSBjb3VudHJpZXMgd2l0aCBpbnRlcmNlcHQgdmFsdWVzIG92ZXIgMC43NQpwcmludChoaWdoX2ludGVyY2VwdF9jb3VudHJpZXMpCmBgYAoKCiMgU2NhdHRlcnBsb3RzIGZvciAnaGlnaF9pbnRlcmNlcHRfY291bnRyaWVzJyBjb250YWlucyB0aGUgdG9wIDE3IGNvdW50cmllcwpgYGB7cn0KIyBDcmVhdGUgc2NhdHRlcnBsb3RzIHdpdGggcmVncmVzc2lvbiBsaW5lcyBmb3IgY291bnRyaWVzIHdpdGggaW50ZXJjZXB0ID4gMC43NQpwbG90cyA8LSBsYXBwbHkoaGlnaF9pbnRlcmNlcHRfY291bnRyaWVzJGNvdW50cnksIGZ1bmN0aW9uKGNvdW50cnkpIHsKICBwIDwtIGdncGxvdChzdWJzZXQoY2xlYW5lZF9kYXRhLCBjb3VudHJ5ID09IGNvdW50cnkpLCBhZXMoeCA9IGFnZSwgeSA9IHJpc2t0YWtpbmcsIGNvbG9yID0gZmFjdG9yKGdlbmRlcikpKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAwLjUpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSB5IH4geCwgc2UgPSBGQUxTRSkgKwogICAgbGFicyh0aXRsZSA9IHBhc3RlKCJMaW5lYXIgUmVncmVzc2lvbiBmb3IiLCBjb3VudHJ5KSwKICAgICAgICAgc3VidGl0bGUgPSBwYXN0ZSgiSW50ZXJjZXB0OiIsIHJvdW5kKGhpZ2hfaW50ZXJjZXB0X2NvdW50cmllcyRpbnRlcmNlcHRbaGlnaF9pbnRlcmNlcHRfY291bnRyaWVzJGNvdW50cnkgPT0gY291bnRyeV0sIDIpKSwKICAgICAgICAgY29sb3IgPSAiR2VuZGVyIikgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIjAiID0gImJsdWUiLCAiMSIgPSAicmVkIiksIGxhYmVscyA9IGMoIk1hbGUiLCAiRmVtYWxlIikpCiAgcHJpbnQocCkKfSkKCiMgU2F2ZSB0aGUgcGxvdHMgaW4gYSBkaXJlY3RvcnkKZGlyLmNyZWF0ZSgiaW5kaXZpZHVhbF9jb3VudHJ5X3Bsb3RzIiwgc2hvd1dhcm5pbmdzID0gRkFMU0UpCnNldHdkKCJpbmRpdmlkdWFsX2NvdW50cnlfcGxvdHMiKQoKZm9yIChpIGluIHNlcV9hbG9uZyhwbG90cykpIHsKICBmaWxlbmFtZSA8LSBwYXN0ZTAoInBsb3RfIiwgaSwgIi5wbmciKQogIGdnc2F2ZShmaWxlbmFtZSwgcGxvdCA9IHBsb3RzW1tpXV0sIHdpZHRoID0gOCwgaGVpZ2h0ID0gNikKfQoKIyBTd2l0Y2ggYmFjayB0byB0aGUgb3JpZ2luYWwgd29ya2luZyBkaXJlY3RvcnkKc2V0d2QoIi4uIikKCnByaW50KCJJbmRpdmlkdWFsIHBsb3RzIGZvciBjb3VudHJpZXMgd2l0aCBpbnRlcmNlcHQgPiAwLjc1IGFyZSBzYXZlZCBpbiB0aGUgJ2luZGl2aWR1YWxfY291bnRyeV9wbG90cycgZGlyZWN0b3J5LiIpCgpgYGAKCiMgU2NhdHRlcnBsb3RzIGZvciAnaGlnaF9pbnRlcmNlcHRfY291bnRyaWVzJyBjb250YWlucyB0aGUgdG9wIDE3IGNvdW50cmllcwpgYGB7cn0KcGxvdHMgPC0gbGFwcGx5KGhpZ2hfaW50ZXJjZXB0X2NvdW50cmllcyRjb3VudHJ5LCBmdW5jdGlvbihjb3VudHJ5KSB7CiAgcCA8LSBnZ3Bsb3Qoc3Vic2V0KGNsZWFuZWRfZGF0YSwgY291bnRyeSA9PSBjb3VudHJ5KSwgYWVzKHggPSByYW5raW5nLngsIHkgPSByaXNrdGFraW5nLCBjb2xvciA9IGZhY3RvcihnZW5kZXIpKSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMC41KSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhID0geSB+IHgsIHNlID0gRkFMU0UpICsKICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiTGluZWFyIFJlZ3Jlc3Npb24gZm9yIiwgY291bnRyeSksCiAgICAgICAgIHN1YnRpdGxlID0gcGFzdGUoIkludGVyY2VwdDoiLCByb3VuZChoaWdoX2ludGVyY2VwdF9jb3VudHJpZXMkaW50ZXJjZXB0W2hpZ2hfaW50ZXJjZXB0X2NvdW50cmllcyRjb3VudHJ5ID09IGNvdW50cnldLCAyKSksCiAgICAgICAgIGNvbG9yID0gIkdlbmRlciIpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIwIiA9ICJibHVlIiwgIjEiID0gInJlZCIpLCBsYWJlbHMgPSBjKCJNYWxlIiwgIkZlbWFsZSIpKQogIHByaW50KHApCn0pCgojIFNhdmUgdGhlIHBsb3RzIGluIGEgZGlyZWN0b3J5CmRpci5jcmVhdGUoImluZGl2aWR1YWxfY291bnRyeV9wbG90cyIsIHNob3dXYXJuaW5ncyA9IEZBTFNFKQpzZXR3ZCgiaW5kaXZpZHVhbF9jb3VudHJ5X3Bsb3RzIikKCmZvciAoaSBpbiBzZXFfYWxvbmcocGxvdHMpKSB7CiAgZmlsZW5hbWUgPC0gcGFzdGUwKCJwbG90XyIsIGksICIucG5nIikKICBnZ3NhdmUoZmlsZW5hbWUsIHBsb3QgPSBwbG90c1tbaV1dLCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCn0KCiMgU3dpdGNoIGJhY2sgdG8gdGhlIG9yaWdpbmFsIHdvcmtpbmcgZGlyZWN0b3J5CnNldHdkKCIuLiIpCgpwcmludCgiSW5kaXZpZHVhbCBwbG90cyBmb3IgY291bnRyaWVzIHdpdGggaW50ZXJjZXB0ID4gMC43NSBhcmUgc2F2ZWQgaW4gdGhlICdpbmRpdmlkdWFsX2NvdW50cnlfcGxvdHMnIGRpcmVjdG9yeS4iKQpgYGAKCiMgQ3JlYXRlIHNjYXR0ZXJwbG90cyB3aXRoIHJlZ3Jlc3Npb24gbGluZXMgZm9yIGluZGl2aWR1YWwgY291bnRyaWVzCmBgYHtyfQojIEV4YW1wbGVzIGZvciBjb3VudHJpZXMKcmVncmVzc2lvbl9yZXN1bHRzIDwtIGRhdGEuZnJhbWUoCiAgY291bnRyeSA9IGMoIkFsZ2VyaWEiLCAiQXJnZW50aW5hIiwgIkF1c3RyaWEiKSwKICBpbnRlcmNlcHQgPSBjKDAuOTIwNTM0MjIsIDAuNTE2OTg4MjIsIDAuNDI2MDY2ODQpLAogIHNsb3BlID0gYygtMC4wMTQ2NjQxODAxLCAtMC4wMTE1NTY5NjIzLCAtMC4wMTA4NzYzMDQyKSwKICByX3NxdWFyZWQgPSBjKDUuMjMyNTI5ZS0wMiwgNS42MzgyNzFlLTAyLCAzLjUzOTgxMGUtMDIJKQopCgojIENyZWF0ZSBzY2F0dGVycGxvdHMgd2l0aCByZWdyZXNzaW9uIGxpbmVzIGZvciBlYWNoIGNvdW50cnkKcGxvdHMgPC0gbGFwcGx5KHNlcV9sZW4obnJvdyhyZWdyZXNzaW9uX3Jlc3VsdHMpKSwgZnVuY3Rpb24oaSkgewogIGNvdW50cnkgPC0gcmVncmVzc2lvbl9yZXN1bHRzJGNvdW50cnlbaV0KICBpbnRlcmNlcHQgPC0gcmVncmVzc2lvbl9yZXN1bHRzJGludGVyY2VwdFtpXQogIHNsb3BlIDwtIHJlZ3Jlc3Npb25fcmVzdWx0cyRzbG9wZVtpXQogIHJfc3F1YXJlZCA8LSByZWdyZXNzaW9uX3Jlc3VsdHMkcl9zcXVhcmVkW2ldCiAgCiAgcCA8LSBnZ3Bsb3Qoc3Vic2V0KGNsZWFuZWRfZGF0YSwgY291bnRyeSA9PSBjb3VudHJ5KSwgYWVzKHggPSBhZ2UsIHkgPSByaXNrdGFraW5nKSkgKwogICAgZ2VvbV9wb2ludCgpICsKICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSB5IH4geCwgc2UgPSBGQUxTRSwgY29sb3IgPSAiYmx1ZSIpICsKICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiTGluZWFyIFJlZ3Jlc3Npb24gZm9yIiwgY291bnRyeSksCiAgICAgICAgIHN1YnRpdGxlID0gcGFzdGUoIkludGVyY2VwdDoiLCByb3VuZChpbnRlcmNlcHQsIDIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiU2xvcGU6Iiwgcm91bmQoc2xvcGUsIDIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiUi1zcXVhcmVkOiIsIHJvdW5kKHJfc3F1YXJlZCwgMikpKQogIHByaW50KHApCn0pCgojIFNhdmUgdGhlIHBsb3RzIGluIGEgZGlyZWN0b3J5CmRpci5jcmVhdGUoImluZGl2aWR1YWxfY291bnRyeV9wbG90cyIsIHNob3dXYXJuaW5ncyA9IEZBTFNFKQpzZXR3ZCgiaW5kaXZpZHVhbF9jb3VudHJ5X3Bsb3RzIikKCmZvciAoaSBpbiBzZXFfYWxvbmcocGxvdHMpKSB7CiAgZmlsZW5hbWUgPC0gcGFzdGUwKCJwbG90XyIsIGksICIucG5nIikKICBnZ3NhdmUoZmlsZW5hbWUsIHBsb3QgPSBwbG90c1tbaV1dLCB3aWR0aCA9IDgsIGhlaWdodCA9IDYpCn0KCiMgU3dpdGNoIGJhY2sgdG8gdGhlIG9yaWdpbmFsIHdvcmtpbmcgZGlyZWN0b3J5CnNldHdkKCIuLiIpCgpwcmludCgiSW5kaXZpZHVhbCBwbG90cyBhcmUgc2F2ZWQgaW4gdGhlICdpbmRpdmlkdWFsX2NvdW50cnlfcGxvdHMnIGRpcmVjdG9yeS4iKQpgYGAKCiMgU2NhdHRlcnBsb3Qgd2l0aCBpbmNsdWRlIGJvdGggaW5kaXZpZHVhbCBjb3VudHJ5IHJlZ3Jlc3Npb24gbGluZXMgYW5kIGFuIG92ZXJhbGwgcmVncmVzc2lvbiBsaW5lCmBgYHtyfQojIENhbGN1bGF0ZSB0aGUgb3ZlcmFsbCByZWdyZXNzaW9uIGxpbmUKb3ZlcmFsbF9sbSA8LSBsbShyaXNrdGFraW5nIH4gYWdlLCBkYXRhID0gY2xlYW5lZF9kYXRhKQoKIyBDcmVhdGUgYSBzY2F0dGVycGxvdCB3aXRoIHNlcGFyYXRlIHJlZ3Jlc3Npb24gbGluZXMgZm9yIGVhY2ggY291bnRyeQojIGFuZCBhbiBvdmVyYWxsIHJlZ3Jlc3Npb24gbGluZQpnZ3Bsb3QoY2xlYW5lZF9kYXRhLCBhZXMoeCA9IGFnZSwgeSA9IHJpc2t0YWtpbmcsIGNvbG9yID0gY291bnRyeSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjUpICsgICAgICAgICAgICAgICAgICAgICAgIyBBZGp1c3QgcG9pbnQgc2l6ZQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIHNpemUgPSAwLjUpICsgIyBTb2xpZCBsaW5lIGZvciBpbmRpdmlkdWFsIGNvdW50cmllcwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IGNvZWYob3ZlcmFsbF9sbSlbMV0sIHNsb3BlID0gY29lZihvdmVyYWxsX2xtKVsyXSwgCiAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMSkgKyAjIEFkZCB0aGUgb3ZlcmFsbCByZWdyZXNzaW9uIGxpbmUgaW4gcmVkCiAgbGFicyh0aXRsZSA9ICJTY2F0dGVycGxvdCB3aXRoIFJlZ3Jlc3Npb24gTGluZXMgZm9yIHJpc2t0YWtpbmcgYW5kIGFnZSBieSBDb3VudHJ5IiwgCiAgICAgICB4ID0gIkFnZSIsIHkgPSAiUmlza3Rha2luZyIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgICAgICAgICAgIyBNb3ZlIHRoZSBsZWdlbmQgYmVsb3cgdGhlIGdyYXBoCiAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjEsICJpbiIpKSAgIyBBZGp1c3QgdGhlIHNpemUgb2YgdGhlIGxlZ2VuZCBrZXkKYGBgCgoKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgQ29tYmluZWQgTGlzdCBvZiBhbGwgMyBmaWxlcwoKIyBQcmVwYXJlIFdhdmUgNQpgYGB7cn0KIyBMb2FkIHRoZSBkYXRhCldWNV9kYXRhIDwtIHJlYWRSRFMoIi9Vc2Vycy9sYXVyYWJhenppZ2hlci9Eb2N1bWVudHMvR2l0SHViL3Jpc2tfd3ZzL2RhdGEvZGF0YXNldC9XVjZfZGF0YXNldF93YXZlXzVfNi9GMDAwMDc5NDQtV1Y1X0RhdGFfUl92MjAxODA5MTIucmRzIikgIyBEYXRhIG9mIFdhdmUgNQoKI3JlbmFtZSB0aGUgdmFyaWFibGVzCldWNV9kYXRhIDwtIFdWNV9kYXRhX2RmICU+JQogIHJlbmFtZShzZXggPSBWMjM1LCBhZ2UgPSBWMjM3LCBjb3VudHJ5ID0gVjIsIHdhdmUgPSBWMSwgcmlza3Rha2luZyA9IFY4NikKV1Y1X2RhdGEKCiNzZWxlY3Qgb25seSB0aGUgdmFyaWFibGVzIG9mIGludGVyZXN0CldWNV9kYXRhIDwtIFdWNV9kYXRhICU+JQogIHNlbGVjdChzZXgsIGFnZSwgY291bnRyeSwgd2F2ZSwgcmlza3Rha2luZykKV1Y1X2RhdGEKCiNkZWNvZGUgdGhlIGNvdW50cnkgbmFtZXMgCmNvdW50cnluYW1lcyA9IHJlYWQuY3N2KCIvVXNlcnMvbGF1cmFiYXp6aWdoZXIvRG9jdW1lbnRzL0dpdEh1Yi9yaXNrX3d2cy9kYXRhL2RhdGFzZXQvV1Y2X2RhdGFzZXRfd2F2ZV81XzYvY291bnRyeW5hbWVzLnR4dCIsIGhlYWRlcj1GQUxTRSxhcy5pcz1UUlVFKQpjb2xuYW1lcyhjb3VudHJ5bmFtZXMpID0gYygiY29kZSIsICJuYW1lIikKV1Y1X2RhdGEkY291bnRyeV9sYWIgPSBjb3VudHJ5bmFtZXMkbmFtZSBbbWF0Y2goV1Y1X2RhdGEkY291bnRyeSwgY291bnRyeW5hbWVzJGNvZGUpXQp0YWJsZShXVjVfZGF0YSRjb3VudHJ5X2xhYikKV1Y1X2RhdGEKYGBgCgojIFByZXBhcmUgV2F2ZSA2CmBgYHtyfQojUmVhZCBEYXRhc2V0IChXYXZlIDYpCldWNl9kYXRhIDwtIGxvYWQoIi9Vc2Vycy9sYXVyYWJhenppZ2hlci9Eb2N1bWVudHMvR2l0SHViL3Jpc2tfd3ZzL2RhdGEvZGF0YXNldC9XVjZfZGF0YXNldF93YXZlXzVfNi9XVjZfRGF0YV9SX3YyMDIwMTExNy5yZGF0YSIpIApXVjZfZGF0YSA8LSBXVjZfRGF0YV9SX3YyMDIwMTExNyAKcHJpbnQoV1Y2X2RhdGEpCmBgYAoKI3JlbmFtZSB2YXJpYWJsZXMgaW4gV2F2ZSA2CmBgYHtyfQpXVjZfZGF0YSA8LSBXVjZfZGF0YSAlPiUKICByZW5hbWUod2F2ZSA9IFYxLCBzZXggPSBWMjQwLCBhZ2UgPSBWMjQyLGNvdW50cnkgPSBWMiwgcmlza3Rha2luZyA9IFY3NikKCiNzZWxlY3Qgb25seSB0aGUgdmFyaWFibGVzIG9mIGludGVyZXN0CldWNl9kYXRhIDwtIFdWNl9kYXRhICU+JQogIHNlbGVjdCh3YXZlLCBzZXgsIGFnZSwgY291bnRyeSwgc2V4LHJpc2t0YWtpbmcpCldWNl9kYXRhCmBgYAojZGVjb2RlIGRhcmFzZXQgKFdhdmUgNikKYGBge3J9CmNvdW50cnluYW1lcyA9IHJlYWQuY3N2KCIvVXNlcnMvbGF1cmFiYXp6aWdoZXIvRG9jdW1lbnRzL0dpdEh1Yi9yaXNrX3d2cy9kYXRhL2RhdGFzZXQvV1Y2X2RhdGFzZXRfd2F2ZV81XzYvY291bnRyeW5hbWVzLnR4dCIsIGhlYWRlcj1GQUxTRSxhcy5pcz1UUlVFKQpjb2xuYW1lcyhjb3VudHJ5bmFtZXMpID0gYygiY29kZSIsICJuYW1lIikKV1Y2X2RhdGEkY291bnRyeV9sYWIgPSBjb3VudHJ5bmFtZXMkbmFtZSBbbWF0Y2goV1Y2X2RhdGEkY291bnRyeSwgY291bnRyeW5hbWVzJGNvZGUpXQp0YWJsZShXVjZfZGF0YSRjb3VudHJ5X2xhYikKV1Y2X2RhdGEKYGBgCiMgUHJlcGFyZSBHUFMgZGF0YXNldCAoY2xlYW5lZF9kYXRhKQpgYGB7cn0KIyBSZW5hbWUgIkNvdW50cnkiIGluICJjb3VudHJ5X2xhYiIKcHJpbnQoY29sbmFtZXMoY2xlYW5lZF9kYXRhKSkKYGBgCgojY29tYmluZSB0aGUgMiBkYXRhc2V0IChXYXZlIDYgKyBXYXZlIDUpCmBgYHtyfQpXVjVfZGF0YQpXVjZfZGF0YQpkYXRhID0gcmJpbmQoV1Y1X2RhdGEsIFdWNl9kYXRhKQpkYXRhCgojbnVtYmVyIG9mIGNvdW50cmllcwoKbGVuZ3RoKHVuaXF1ZShkYXRhJGNvdW50cnlfbGFiKSkKYGBgCgoKIyBNZXJnZSB0aGUgZGF0YXNldHMgYmFzZWQgb24gY29tbW9uIHZhcmlhYmxlcwpgYGB7cn0KIyBGaW5kIGNvbW1vbiBjb3VudHJpZXMgYmV0d2VlbiB0aGUgdHdvIGRhdGFzZXRzCmNvbW1vbl9jb3VudHJpZXMgPC0gaW50ZXJzZWN0KGRhdGEkY291bnRyeV9sYWIsIGNsZWFuZWRfZGF0YSRjb3VudHJ5KQoKIyBEaXNwbGF5IHRoZSBjb21tb24gY291bnRyaWVzCnByaW50KGNvbW1vbl9jb3VudHJpZXMpCgpgYGAKCiMgRmluZCBjb3VudHJpZXMgaW4gImRhdGEiIGJ1dCBub3QgaW4gImNsZWFuZWRfZGF0YSIKYGBge3J9CmNvdW50cmllc19vbmx5X2luX2RhdGEgPC0gc2V0ZGlmZihkYXRhJGNvdW50cnlfbGFiLCBjbGVhbmVkX2RhdGEkY291bnRyeSkKCiMgRmluZCBjb3VudHJpZXMgaW4gImNsZWFuZWRfZGF0YSIgYnV0IG5vdCBpbiAiZGF0YSIKY291bnRyaWVzX29ubHlfaW5fY2xlYW5lZF9kYXRhIDwtIHNldGRpZmYoY2xlYW5lZF9kYXRhJGNvdW50cnksIGRhdGEkY291bnRyeV9sYWIpCgojIERpc3BsYXkgdGhlIHJlc3VsdHMKY2F0KCJDb3VudHJpZXMgb25seSBpbiAnZGF0YSc6IiwgY291bnRyaWVzX29ubHlfaW5fZGF0YSwgIlxuIikKY2F0KCJDb3VudHJpZXMgb25seSBpbiAnY2xlYW5lZF9kYXRhJzoiLCBjb3VudHJpZXNfb25seV9pbl9jbGVhbmVkX2RhdGEsICJcbiIpCmBgYAoKCgo=